window.JSONConverter =  function(){
	var pn = {
		convert : function(data, excludeProc){
			var json = "";

			if ( $.isObj(data) ) {
				json = this.formatObj(data, excludeProc);
			}
			else if ( $.isStr(data) ) {
				json = this.fromString(data);
			}

			return(json);
		},
		fromString : function(data)
		{
			$.eval("var newObj = eval("+ data +")");

			return($.eval("newObj"));
		},
		formatObj : function(data, excludeProc) {
			var json = "{";
			var obj = data.toArray();
			var $me = this;

			for(var item in data ) {

				json += "\n\""+ item +"\" : "+ $me.formatType( data[item], excludeProc ) + ",";
			}

			json = json.substr(0, json.length - 1);
			json += "}\n";

			return( json );
		},
		formatString : function(data)
		{
			var sDate = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(data);

			if (sDate) {
				// Fecha ISO.
				//
				return( new Date(Date.UTC(+sDate[1], +sDate[2] - 1,
				+sDate[3], +sDate[4], +sDate[5], +sDate[6])) );
			}

			data = data.replace(/\'/ig, "\'");
			data = data.replace(/\"/ig, "\"");

			data = "\""+ data +"\"";

			return(data);
		},
		formatArray : function(data)
		{
			var retData = "[";

			for( var i = 0; i < data.length; i++ ) {
				retData += this.formatType( data[i] );

				if ( i < (data.length - 1) )
					retData += ",";
			}

			retData += "]";

			return(retData);
		},
		formatType : function(data, excludeProc)
		{
			var json = "";

			if ( $.isArray(data) ) {
				return( this.formatArray(data) );
			}
			else if ( $.isStr(data) ) {
				return( this.formatString(data) );
			}
			else if ( $.isProc(data) ) {
				if ( excludeProc )
					return(null);

				return( data.toString() );
			}
			else if ( $.isNum(data) ){
				return( isFinite(data) ? String(data) : "null" );
			}
			else if ( data instanceof Date ) {
				return(
					data.getUTCFullYear()   + '-' +
					(data.getUTCMonth() + 1) + '-' +
					this.minValue(data.getUTCDate())      + 'T' +
					this.minValue(data.getUTCHours())     + ':' +
					this.minValue(data.getUTCMinutes())   + ':' +
					this.minValue(data.getUTCSeconds())   + 'Z'
				);
			}
			else if ( data == null ) {
				return(null);
			}
			else if ( $.isObj(data) ) {
				return( this.formatObj(data, excludeProc) );
			}

			return(data);
		},
		minValue : function(n) {
			return( n < 10 ? '0' + n : n );
		}
	};

	return( pn );
};

Array.prototype.extend({
	toJSON : function(name){
		name = name || "array";

		return( "{" + name + ":" + JSONConverter().formatType(this) + "}" );
	}
}, true);

Object.prototype.extend({
	toJSON : function(){
		return( JSONConverter().convert(this) );
	}
});
